package service

import (
	"context"
	"encoding/json"
	"errors"
	"relation/api"
	"strconv"

	"dubbo.apache.org/dubbo-go/v3/common/logger"
	"dubbo.apache.org/dubbo-go/v3/config"
	_ "dubbo.apache.org/dubbo-go/v3/imports"
)

/*
user_1_id usr_2_id relation
id小的在前
*/

var commonProvider *api.CommonClientImpl
var userProvider *api.UserProviderClientImpl

type RelationProviderImpl struct {
	api.UnimplementedRelationProviderServer
}

func OkUr(ua int64, ub int64, rel api.RelationType) (*api.UserRelation, error) {
	return &api.UserRelation{
		UserAId:  ua,
		UserBId:  ub,
		Relation: rel,
	}, nil
}

func OkUl(arr []int64, size int64) (*api.UserList, error) {
	return &api.UserList{List: arr, Size: size}, nil
}

func FailUr(err error) (*api.UserRelation, error) {
	return nil, err
}

func FailUl(err error) (*api.UserList, error) {
	return nil, err
}

/*
checkUser
- 改为使用user的方法，在内部更改就行
- 检查用户是否合法
*/
func checkUser(ctx context.Context, uid int64) bool {
	_, err := userProvider.Find(ctx, &api.User{
		Id: uid,
	})
	return err == nil
}

/*
getABRelation
- 获取AB的关系
返回A对B的关系
*/
func getABRelation(ctx context.Context, aid int64, bid int64) (api.RelationType, error) {
	if aid == bid {
		return 0, errors.New("a和b不应该是同一个人")
	}

	if aid < bid {
		get, err := commonProvider.Get(ctx, &api.Query{
			Database: "douyin",
			Table:    "relation",
			Key:      []string{"relation"},
			Where: []*api.Query_Condition{
				{
					Key:   []string{"user_a_id", "user_b_id"},
					Value: []string{strconv.FormatInt(aid, 10), strconv.FormatInt(bid, 10)},
					Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
				},
			},
			Result: api.Query_RELATION,
		})
		if err != nil {
			return api.RelationType_NONE, err
		}

		var list []*api.UserRelation
		err = json.Unmarshal(get.Value, &list)
		if err != nil {
			return 0, err
		}

		// 查找不到，AB关系为无关系
		if list == nil || len(list) == 0 {
			return api.RelationType_NONE, nil
		} else {
			return list[0].Relation, nil
		}

	} else {
		get, err := commonProvider.Get(ctx, &api.Query{
			Database: "douyin",
			Table:    "relation",
			Key:      []string{"relation"},
			Where: []*api.Query_Condition{
				{
					Key:   []string{"user_a_id", "user_b_id"},
					Value: []string{strconv.FormatInt(bid, 10), strconv.FormatInt(aid, 10)},
					Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
				},
			},
			Result: api.Query_RELATION,
		})
		if err != nil {
			return api.RelationType_NONE, err
		}

		var list []*api.UserRelation
		err = json.Unmarshal(get.Value, &list)
		if err != nil {
			return 0, err
		}

		// 查找不到，AB关系为无关系
		if list == nil || len(list) == 0 {
			return api.RelationType_NONE, nil
		} else {
			re := list[0].Relation
			if re == api.RelationType_FOLLOWER {
				return api.RelationType_FOLLOW, nil
			} else if re == api.RelationType_FOLLOW {
				return api.RelationType_FOLLOWER, nil
			} else {
				return re, nil
			}

		}
	}
}

func updateRelation(ctx context.Context, a int64, b int64, re api.RelationType) error {
	// 保证小Id在前
	if a < b {
		_, err := commonProvider.Update(ctx, &api.Value{
			Database: "douyin",
			Table:    "relation",
			Key:      []string{"user_a_id", "user_b_id", "relation"},
			Value:    []string{strconv.FormatInt(a, 10), strconv.FormatInt(b, 10), strconv.FormatInt(int64(api.RelationType_value[re.String()]), 10)},
		})
		if err != nil {
			return err
		}
	} else {
		if re == api.RelationType_FRIEND {
			return updateRelation(ctx, b, a, re)
		} else if re == api.RelationType_FOLLOW {
			return updateRelation(ctx, b, a, api.RelationType_FOLLOWER)
		} else if re == api.RelationType_FOLLOWER {
			return updateRelation(ctx, b, a, api.RelationType_FOLLOW)
		} else {
			return updateRelation(ctx, b, a, api.RelationType_NONE)
		}
	}
	return nil
}

/*
Follow
关注
- 若A已经关注B 不动
- 若A未关注B  设为A关注B
- 若B已经关注A 设为互关
*/
func (s *RelationProviderImpl) Follow(ctx context.Context, in *api.UserRelation) (*api.UserRelation, error) {
	logger.Infof("Relation Follow get UserRelation = %s\n", in)
	// 参数校验
	// 非法用户情况
	if !checkUser(ctx, in.UserAId) || !checkUser(ctx, in.UserBId) {
		return FailUr(errors.New("用户非法"))
	}
	if in.UserAId == in.UserBId {
		return FailUr(errors.New("不能关注自己"))
	}

	// 获取用户关系
	relation, err := getABRelation(ctx, in.UserAId, in.UserBId)
	if err != nil {
		return FailUr(err)
	}
	switch relation {
	case api.RelationType_NONE:
		// 无关系，改为A follow B
		if err := updateRelation(ctx, in.UserAId, in.UserBId, api.RelationType_FOLLOW); err != nil {
			return FailUr(err)
		}
	case api.RelationType_FOLLOW:
		//  若A已经关注B 不动
		return OkUr(in.UserAId, in.UserAId, in.Relation)
	case api.RelationType_FOLLOWER:
		// 改为互关
		if err := updateRelation(ctx, in.UserAId, in.UserBId, api.RelationType_FRIEND); err != nil {
			return FailUr(err)
		}
	case api.RelationType_FRIEND:
		// 互关，不动
		return OkUr(in.UserAId, in.UserAId, in.Relation)
	}
	return OkUr(in.UserAId, in.UserAId, in.Relation)
}

/*
UnFollow
取关
- 若AB无关	不动
- 若A关注B	AB无关 B也要更新
- 若A被关注B	不动
- 若A互关B	变为A被关注B,B关注A
*/
func (s *RelationProviderImpl) UnFollow(ctx context.Context, in *api.UserRelation) (*api.UserRelation, error) {
	logger.Infof("Relation UnFollow get UserRelation = %s\n", in)
	// 非法用户情况
	if !checkUser(ctx, in.UserAId) || !checkUser(ctx, in.UserBId) {
		return FailUr(errors.New("用户非法"))
	}
	// 参数校验
	// - 根据db中ab的关系进行不同的处理
	relation, err := getABRelation(ctx, in.UserAId, in.UserBId)
	if err != nil {
		return FailUr(err)
	}

	switch relation {
	case api.RelationType_NONE:
		return OkUr(in.UserAId, in.UserAId, in.Relation)
	case api.RelationType_FOLLOW:
		// 若A已经关注B -> a none b
		if err := updateRelation(ctx, in.UserAId, in.UserBId, api.RelationType_NONE); err != nil {
			return FailUr(err)
		}
		return OkUr(in.UserAId, in.UserBId, api.RelationType_NONE)
	case api.RelationType_FOLLOWER:
		return OkUr(in.UserAId, in.UserAId, in.Relation)
	case api.RelationType_FRIEND:
		// 互关 -> a follower b
		if err := updateRelation(ctx, in.UserAId, in.UserBId, api.RelationType_FOLLOWER); err != nil {
			return FailUr(err)
		}
		return OkUr(in.UserAId, in.UserBId, api.RelationType_FOLLOWER)
	}
	return FailUr(errors.New("UnFollow: false location"))
}

/*
IsFollow
- 返回A与B的关系
*/
func (s *RelationProviderImpl) IsFollow(ctx context.Context, in *api.UserRelation) (*api.UserRelation, error) {
	logger.Infof("Relation IsFollow get UserRelation = %s\n", in)
	// 非法用户情况
	if !checkUser(ctx, in.UserAId) || !checkUser(ctx, in.UserBId) {
		return FailUr(errors.New("用户非法"))
	}
	// 查询db 获取a和b的关系
	relation, err := getABRelation(ctx, in.UserAId, in.UserBId)
	if err != nil {
		return FailUr(err)
	}

	if relation == api.RelationType_FRIEND || relation == api.RelationType_FOLLOW {
		return &api.UserRelation{}, nil
	}

	return nil, errors.New("no relation")
}

/*
FindFollow
- 获取A的关注Id列表
*/
func (s *RelationProviderImpl) FindFollow(ctx context.Context, in *api.UserRelation) (*api.UserList, error) {
	logger.Infof("Relation FindFollow get UserRelation = %s\n", in)
	// 非法用户情况
	if !checkUser(ctx, in.UserAId) {
		return FailUl(errors.New("用户非法"))
	}
	//  查询db 获取A的关注Id列表
	//  或关系？ follow or friends
	get, err := commonProvider.Get(ctx, &api.Query{
		Database: "douyin",
		Table:    "relation",
		Key:      []string{"user_a_id", "user_b_id", "relation"},
		Where: []*api.Query_Condition{
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOW.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOWER.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
		},
		//OrderBy: nil,
		//Limit:   nil,
		Result: api.Query_RELATION,
	})
	if err != nil {
		return FailUl(err)
	}
	var list []*api.UserRelation
	err = json.Unmarshal(get.Value, &list)
	if err != nil {
		return FailUl(err)
	}
	arr := make([]int64, 0)
	for _, v := range list {
		if v.UserAId == in.UserAId {
			arr = append(arr, v.UserBId)
		} else {
			arr = append(arr, v.UserAId)
		}
	}
	return OkUl(arr, 0)
}

/*
CountFollow
- 获取关注列表,获取长度
*/
func (s *RelationProviderImpl) CountFollow(ctx context.Context, in *api.UserRelation) (*api.UserList, error) {
	logger.Infof("Relation CountFollow get UserRelation = %s\n", in)
	// 非法用户情况
	if !checkUser(ctx, in.UserAId) {
		return FailUl(errors.New("用户非法"))
	}
	// count
	get, err := commonProvider.Count(ctx, &api.Query{
		Database: "douyin",
		Table:    "relation",
		Key:      []string{"user_a_id", "user_b_id", "relation"},
		Where: []*api.Query_Condition{
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOW.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOWER.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
		},
		//OrderBy: nil,
		//Limit:   nil,
		Result: api.Query_RELATION,
	})
	if err != nil {
		return FailUl(err)
	}
	return OkUl(nil, get.Size)
}

/*
FindFollower
- 获取A的粉丝Id列表
*/
func (s *RelationProviderImpl) FindFollower(ctx context.Context, in *api.UserRelation) (*api.UserList, error) {
	logger.Infof("Relation FindFollower get UserRelation = %s\n", in)
	// 非法用户情况
	if !checkUser(ctx, in.UserAId) {
		return FailUl(errors.New("用户非法"))
	}
	// 或关系 follower or friends
	get, err := commonProvider.Get(ctx, &api.Query{
		Database: "douyin",
		Table:    "relation",
		Key:      []string{"user_a_id", "user_b_id", "relation"},
		Where: []*api.Query_Condition{
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOWER.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOW.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
		},
		//OrderBy: nil,
		//Limit:   nil,
		Result: api.Query_RELATION,
	})
	if err != nil {
		return FailUl(err)
	}
	var list []*api.UserRelation
	err = json.Unmarshal(get.Value, &list)
	if err != nil {
		return FailUl(err)
	}

	arr := make([]int64, 0)
	for _, v := range list {
		if v.UserAId == in.UserAId {
			arr = append(arr, v.UserBId)
		} else {
			arr = append(arr, v.UserAId)
		}
	}
	return OkUl(arr, 0)
}

/*
CountFollower
- 获取粉丝数目
*/
func (s *RelationProviderImpl) CountFollower(ctx context.Context, in *api.UserRelation) (*api.UserList, error) {
	logger.Infof("Relation CountFollower get UserRelation = %s\n", in)
	// 非法用户情况
	if !checkUser(ctx, in.UserAId) {
		return FailUl(errors.New("用户非法"))
	}
	// count
	get, err := commonProvider.Count(ctx, &api.Query{
		Database: "douyin",
		Key:      []string{"user_a_id", "user_b_id", "relation"},
		Where: []*api.Query_Condition{
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOWER.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FOLLOW.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
		},
		//OrderBy: nil,
		//Limit:   nil,
		Result: api.Query_RELATION,
	})
	if err != nil {
		return FailUl(err)
	}
	return OkUl(nil, get.Size)
}

/*
FindFriend
- 获取互关Id列表
*/
func (s *RelationProviderImpl) FindFriend(ctx context.Context, in *api.UserRelation) (*api.UserList, error) {
	logger.Infof("Relation FindFriend get UserRelation = %s\n", in)
	// 非法用户情况 ab两个要保证都合法
	if !checkUser(ctx, in.UserAId) {
		return FailUl(errors.New("用户非法"))
	}
	// 查询db
	get, err := commonProvider.Get(ctx, &api.Query{
		Database: "douyin",
		Table:    "relation",
		Key:      []string{"user_b_id"},
		Where: []*api.Query_Condition{
			{
				Key:   []string{"user_a_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id", "relation"},
				Value: []string{strconv.FormatInt(in.UserAId, 10), strconv.FormatInt(int64(api.RelationType_value[api.RelationType_FRIEND.String()]), 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE, api.Query_Condition_NE},
			},
		},
		Result: api.Query_RELATION,
	})
	if err != nil {
		return FailUl(err)
	}
	var list []*api.UserRelation
	err = json.Unmarshal(get.Value, &list)
	if err != nil {
		return FailUl(err)
	}
	arr := make([]int64, 0)
	for _, v := range list {
		if v.UserAId == in.UserAId {
			arr = append(arr, v.UserBId)
		} else {
			arr = append(arr, v.UserAId)
		}
	}
	return OkUl(arr, 0)
}

/*
init
*/
func init() {
	commonProvider = new(api.CommonClientImpl)
	userProvider = new(api.UserProviderClientImpl)

	config.SetProviderService(&RelationProviderImpl{})
	config.SetConsumerService(commonProvider)
	config.SetConsumerService(userProvider)
}
